/***************************************************************
                       next.c
fpp variables: 
showburied, clhigh, root, trail, fileName, merging, centre_pos

clone.match is parent name, ' ' is no parent
clone.parent is parent index
clone.mattype is PARENT, APPROX, EXACT

Sz.match is number of matching bands
Sz.parent is clone.match
9 apr 98 - can't bury seq clone in Z_buryhigh
**************************************************************/
#include <stdio.h>
#include <pwd.h>
#include <malloc.h>
#include <limits.h>
#include "clam.h"
#include <gtk/gtkwidget.h>

#define graphQuery messQuery

extern BOOL ZboolCpM();
             /** fpp functions **/
extern int textClone;
extern void displaymess(), recalccontigs(), highlightnodraw(), point2();
extern void redrawfingerprints(), move_selected();
extern int unbury(), bury();

extern int grule, Zall_ok(), fppFindClone(), cloneHigh();
extern void ZhighP(), Set1(), ZclearHigh(), ZhighClp();

extern char scoreText[40], set1Text[14];
extern int removeBox, compareBox, findburyBox, buryBox, unburyBox;
extern int qstuff; /*efriedr 12/6/01*/
extern GtkWidget *ctg_window; /*fred 4/17/03*/
extern void refresh_all_track_colors();

int Gzn=0, Bzn=0, Zprtype=0;

#define Show {if (graphActivate(g9a)){graphPop(); graphRedraw();} \
              if (graphActivate(g9b)){graphPop(); graphRedraw();} \
              if (graphActivate(g9c)){graphPop(); graphRedraw();}}
#define Output {if (Pz.logFlag) {fprintf(Zlogfp,"%s",ZBuf); fflush(Zlogfp);}\
                if (Pz.stdFlag) {\
                   printf("%s",ZBuf); fflush(stdout);}}
#define IsBuried2(nb, f) (nb - Sz.match <=  (int) ((float) f * nb))
#define NoGray  if (graphActivate(g9c)) {\
                    graphRedraw(); \
                    graphBoxDraw(findburyBox, BLACK, WHITE);\
                    graphBoxDraw(compareBox, BLACK, WHITE);}
#define IsMerge if (merging) {sprintf(scoreText,"Contig in merge state");\
                              Show; NoGray; return;}
#define IsMerge2 if (merging) {sprintf(scoreText,"Contig in merge state");\
                              Show; NoGray; return 0;}

extern void  ZhighCin(), ZclearHigh();
extern int loadCz(), loadCzfast(), Zgetdiff(), showClam();

void  Z_OneCtg(), Z_OneNext(),Z_OneAgain(), Z_OneAdd();
void Z_BurCtg(), Z_BurNext(),Z_BurAgain(), Z_BurAdd();

static void Z_removeHigh(), Z_buryHigh(), Z_unburyHigh();

#define LGZ 500
static struct tmpGz {
   int index, box;
   int w, np, left, x;
   int loner[LGZ];
   CLONE *clp[LGZ];
} Gz; 

static struct tmpBz {
   int  diff, cin, nbands, mattype, parent;
} *Bz;
static int  Bzp, Bzz, Bznp, Bznb;

static CLONE my_clone;

static char msg[256];
int removeFlag=0, buryFlag=0, unburyFlag=0;

static struct save_sel {
  int cin, sel;
} *SS;
/****************************************************************
                    DEF: pickClam();
called from fpgen/point2 when clone is picked from contig window
*****************************************************************/
int pickClam(struct contig *p)
{

   if(p==NULL) return FALSE; 
   if (!(buryFlag || unburyFlag || removeFlag)) return FALSE;
   if (!graphActivate(g9c)) return FALSE;

   if (buryFlag) Z_buryHigh(p); 
   else if (unburyFlag)  Z_unburyHigh(p);
   else if (removeFlag)  Z_removeHigh(p);
   return TRUE;
}
/**************************************************************
                    DEF: Zsave_selected()
***************************************************************/
void Zsave_selected(int set)
{
struct contig *p;
int i;

   SS = (struct save_sel *) 
      malloc(sizeof(struct save_sel) * (contigs[currentctg].count+1));
   NOMEM2(SS,"SS Next");
   for (i=0, p = root; p != NULL; p = p->new, i++) {
       SS[i].sel = arrp(acedata,p->next,CLONE)->selected;
       SS[i].cin = p->next;
       if (!set) arrp(acedata,p->next,CLONE)->selected = 0;
   }
   SS[i].sel=2;
 if (i!=contigs[currentctg].count)
   printf("FPC error: Contig clone count disagree %d %d\n",i, contigs[currentctg].count);
}
/**************************************************************
                    DEF: Zredo_selected()
***************************************************************/
int Zredo_selected(int flag)
{
int i,j;
CLONE *clp;

      /* this gets called after moving one or more clones, readjust markers */
   if (flag) {
     PRTMESS=0;
     move_selected(currentctg, currentctg, 0); 
     PRTMESS=1;
   }
   for (j=i=0; SS[i].sel!=2; i++) {
       clp = arrp(acedata,SS[i].cin,CLONE);
       if (clp->ctg==currentctg) {
          clp->selected = SS[i].sel;
          if (SS[i].sel==1) j=1;
       }
   }
   free(SS);
   return j;
}
/**************************************************************
                    DEF: initZbury()
***************************************************************/
void initZbury()
{
   Zprtype=0;
   Bzn = Gzn = -1;
   buryFlag=unburyFlag=0;
   if (Bz!=NULL) ZFREE(Bz, "Bz");
}
/**************************************************************
                    DEF: Zbury_type()
child and parent are indices in the clone array
***************************************************************/
int Zbury_type(int child, int parent)
{
      if(!bands) /* if no bands then read them in*/
        if(fpRead()< 0 ){
         printf("Error reading cor\n");
         return PSEUDO;
      }       
      if (!loadCz(&C1z, parent)) return PSEUDO;
      if (!loadCz(&C2z, child)) return PSEUDO;
      Zgetmatch(&C1z,&C2z,&Sz);
      if (Sz.match==C2z.nbands) return EXACT;
      else if IsBuried(C2z.nbands) return APPROX;
      else return PSEUDO;
}
/**************************************************************
                    DEF: Zupdate_cin()
called from fpp when clone structure indices change
***************************************************************/
void Zupdate_cin(from, to)
{
    if (Zprtype==1) {
        sprintf(scoreText,"Canonical; list of-of-date");
        Show;
    } 
    if (Zprtype==2) {
        sprintf(scoreText,"Compare; list of-of-date");
        Show;
    } 
    initZbury(); NoGray; 
}
/****************************************************************
                    DEF: child_adjustment();
*****************************************************************/
int child_adjustment(CLONE *par, CLONE *chi)
{
int ap=0;

     if (chi->x == chi->y) { /* called from OK via Zsel_bury */
         chi->x = par->x;
         chi->y = par->x + chi->fp->b2;
         return 1;
     }
     if  (chi->mattype == PSEUDO) { /* must overlap */
          if (par->x < chi->y && chi->x < par->y) return 0;
     }
     else if (chi->mattype == APPROX) { /* must not extend to far from parent */
        ap = (int) ((float) par->fp->b2 * Pz.burFlt) + 1;
        if  ((par->x - chi->x) <= ap && (chi->y - par->y) <= ap) return 0;
     }
     else  /* must be contained in */
        if (chi->x >= par->x && chi->x < par->y && chi->y > par->x && 
            chi->y <= par->y) return 0;
         
     if (PRTMESS) {
       sprintf(msg,"Adjust coords for buried clone %s parent %s",chi->clone, par->clone);
       displaymess(msg);
     }

     chi->selected = par->selected = 1; /* so move_selected will adjust markers */
     if (chi->mattype == APPROX) {
         if (chi->x < par->x) {
            ap = par->x - ap;
            chi->x = ap;
            chi->y = ap + (chi->fp->b2 - 1);
         }
         else {
             ap = par->y + ap;
             chi->y = ap;
             chi->x = ap - (chi->fp->b2 - 1);
         }
     }
     else {
         if (chi->x < par->x) {
              chi->x = par->x;
              chi->y = par->x + (chi->fp->b2 - 1);
         }
         else {
              chi->y = par->y;
              chi->x = par->y - (chi->fp->b2 - 1);
         }
     }
     return 1;
}
/****************************************************************
                    DEF: Z_bury();
*****************************************************************/
void Z_buryStop()
{
   if (!graphActivate(g9c)) return;
   if (merging) {
      buryFlag=0;
      IsMerge;
   }

    buryFlag = !buryFlag;
    if (buryFlag) {
       removeFlag = unburyFlag = 0;
       graphBoxDraw(buryBox, BLACK, LIGHTRED);
       graphBoxDraw(unburyBox, BLACK, WHITE);
       graphBoxDraw(removeBox, BLACK, WHITE);
    }
    else {
       graphBoxDraw(buryBox, BLACK, WHITE);
    }
}
/****************************************************************
                    DEF: Z_bury();
*****************************************************************/
void Z_unburyStop()
{
   if (!graphActivate(g9c)) return;

    unburyFlag = !unburyFlag;
    if (unburyFlag) {
       removeFlag = buryFlag = 0;
       graphBoxDraw(unburyBox, BLACK, LIGHTRED);
       graphBoxDraw(buryBox, BLACK, WHITE);
       graphBoxDraw(removeBox, BLACK, WHITE);
    }
    else {
       graphBoxDraw(unburyBox, BLACK, WHITE);
    }
}
/****************************************************************
                    DEF: Z_remove();
*****************************************************************/
void Z_removeStop()
{
   if (!graphActivate(g9c)) return;
   if (merging) {
      removeFlag=0;
      IsMerge;
   }
    removeFlag = !removeFlag;
    if (removeFlag) {
       unburyFlag = buryFlag = 0;
       graphBoxDraw(removeBox, BLACK, LIGHTRED);
       graphBoxDraw(buryBox, BLACK, WHITE);
       graphBoxDraw(unburyBox, BLACK, WHITE);
    }
    else {
       graphBoxDraw(removeBox, BLACK, WHITE);
    }
}
/****************************************************************
                   DEF: removeHigh
****************************************************************/
static void Z_removeHigh(struct contig *cl)
{
CLONE *c2;

  IsMerge;
  c2 = arrp(acedata, cl->next, CLONE);
  sprintf(scoreText, "Remove %s from ctg%d",c2->clone, c2->ctg); Show;
  Z_removeStop();

  Zsave_selected(0);
  c2->selected = 1;
  move_selected(currentctg,0, 0);
  
  if (Zredo_selected(0))
      ctgdisplay(currentctg);
}
/****************************************************************
                   DEF: Z_buryHigh
Bury in 1
****************************************************************/
static void Z_buryHigh(struct contig *cl)
{
int  draw=0, index1;
CLONE *c1, *c2;
struct contig *p;

  IsMerge;
  if(!fppFindClone(set1Text,&index1)) {   /* find clone */
      sprintf(scoreText,"ERROR could not find clone1 %s",set1Text); Show;
      return;
  }
  c1 = arrp(acedata, index1, CLONE);
  if (index1 == cl->next) {
      sprintf(scoreText,"ERROR cannot bury oneself"); Show;
      buryFlag=0;
      if (graphActivate(g9c)) graphBoxDraw(buryBox, BLACK, WHITE);
      return;
  }
  if (c1->parent!= -1) {
      sprintf(scoreText,"ERROR Clone1 %s is buried",set1Text); Show;
      buryFlag=0;
      if (graphActivate(g9c)) graphBoxDraw(buryBox, BLACK, WHITE);
      return;
  }

  c2 = arrp(acedata, cl->next, CLONE);
  if (c2->ctg != c1->ctg) {   /* find clone */
      sprintf(scoreText,"Clone %s not in contig", c2->clone); Show;
      return;
  }
  if (IsSeq(c2)) { 
      sprintf(scoreText,"*Clone %s sequenced",c2->clone); Show;
      fprintf(stderr,"Warning: Clone %s has sequenced status, so will not be buried\n",
                       c2->clone); 
      return;
  }
  if (c2->mattype == PARENT || c2->mattype == PSPARENT) {
      sprintf(scoreText,"*Clone %s canonical",c2->clone); Show;
      return;
  }
  if (c2->parent != -1) {
      sprintf(scoreText,"*Clone %s is buried",c2->clone); Show;
      return;
  }
  ZclearHigh();
  PRTMESS=1;
  if (bury(cl->next, index1)) {
      c2->mattype = Zbury_type(cl->next, index1);
      Zsave_selected(0);
      child_adjustment(c1, c2);
      Zredo_selected(1);
      sprintf(scoreText, "Bury %s in %s",c2->clone,c1->clone); Show;
  }
  Z_buryStop();
  for (p = root; p != NULL; p = p->new)
      if (p->next == index1) {
         if (clhigh == p) highlightnodraw(FALSE); /* otherwise, pops up */
         draw = cloneHigh(p, 1);
         break;
      }
  if (!draw) ctgdisplay(currentctg); 
}
/****************************************************************
                   DEF: unburyHigh
****************************************************************/
static void Z_unburyHigh(struct contig *cl)
{
CLONE *c2, *clp;
int i, draw;

  IsMerge;
  ZclearHigh();
  c2 = arrp(acedata, cl->next, CLONE);
  if (c2->mattype == PARENT || c2->mattype == PSPARENT) {
      if (messQuery("Clone is canonical. Unbury all children?"))
      {
         sprintf(scoreText,"Clone %s un-canonicaled",c2->clone); 
         for (i=contigs[c2->ctg].start; i != -1; i = clp->next) 
         {
            clp = arrp(acedata,i,CLONE);
            if (strcmp(clp->match, c2->clone)==0)
                  unbury(i);
         }
      }
      else sprintf(scoreText,"Clone %s canonical",c2->clone); 
  }
  else if (c2->parent == -1) {
      sprintf(scoreText,"Clone %s not buried",c2->clone); Show;
      return; /* do not unstop */
  }
  else if (unbury(cl->next)) {
     sprintf(scoreText, "UnBury %s",c2->clone); 
  }
  Show;
  Z_unburyStop();
  draw = cloneHigh(cl, 0);
  if (!draw) ctgdisplay(currentctg);
}
/***************************************************************8
                      Compare Singles 
****************************************************************/
/****************************************************************
                      DEF: Z_OneCtg
****************************************************************/
void Z_OneCtg()
{
struct contig *p;
struct list *lp;
int i;
int nctg=0, total=0, cnt=0;
char str[200], mk[10];

  IsMerge;
  if (!Zall_ok(1, 3)) return; 

  if (Bzn!=-1) {
     if (graphActivate(g9c))
        graphBoxDraw(findburyBox, BLACK, WHITE);
     ZFREE(Bz, "Bz"); 
     Bzn = -1;
  }
  Zprtype=0;
  Gzn = Gz.w = 0;

  if (classctg == CLONECLASS && graphExists(g2)) goto LIST;

  if (contigs[0].count==0) {
     sprintf(scoreText,"No singletons"); Show;
     return;
  }

  sprintf(ZBuf,
   "\n>> Singles --> Ctg%d (Tol %d Cutoff %.0e%s)\n", 
               currentctg, Pz.tol, Pz.cutFlt, CpMtype[Cp.useFlag]); Output;
  Zprtype=2;
  for (i=contigs[0].start; i != -1; i = my_clone.next) 
  {
     if (graphInterruptCalled()) {
          printf("User Interrupt - pre-mature termination of Compare Single\n");
          break;
     } 
     my_clone = arr(acedata,i,CLONE);
     if (my_clone.fp == NULL) continue;
     if (my_clone.clone[0]=='!') continue;
     if (my_clone.match[0]!=' ') continue; /* V2.2 - no children */
     if (!loadCz(&C1z, i)) continue;
     
     cnt=0;
     for (p = root; p != NULL; p = p->new)
     {
        if (!loadCz(&C2z, p->next)) continue;
        Zsulston(&C1z,&C2z,&Sz);
        if (ZboolCpM()) {
           if (Sz.mark > 0) sprintf(mk, "%2d",Sz.mark);
           else strcpy(mk,"  ");;
           sprintf(ZBuf, "%2d. %12s %2db  %12s %2db  %3d %.0e %s %12s    %s\n", 
             Gzn+1,
             C1z.clone, C1z.nbands, C2z.clone, C2z.nbands, Sz.match, Sz.prob, 
             mk, C2z.parent, C2z.fpnum); Output; 
           cnt++;
        }
     }
     total+= cnt;
     if (cnt > 0) Gz.loner[Gzn++]=i;
     if (Gzn == LGZ) {
        sprintf(str, "Compare Singles: exceeded internal list limit");
        displaymess(str);
        break;
     }
  }
  sprintf(scoreText,"Singles %d  Hits %d", Gzn, total); Show;
  goto DONE;

LIST: ;
  sprintf(ZBuf,
   "\n>> Keyset --> Ctg%d (Tol %d, Cutoff %.0e%s)\n", 
               currentctg, Pz.tol, Pz.cutFlt, CpMtype[Cp.useFlag]); Output;
  Zprtype=1;
  for (lp = listroot; lp!=NULL; lp = lp->next) 
  {
     if (graphInterruptCalled()) {
          printf("User Interrupt - pre-mature termination of Compare KeySet\n");
          break;
     } 
     my_clone = arr(acedata,lp->index,CLONE);
     if (my_clone.fp == NULL) continue;
     if (my_clone.ctg == currentctg) {nctg++; continue;}
     if (!loadCz(&C1z, lp->index)) continue;
     
     cnt=0;
     for (p = root; p != NULL; p = p->new)
     {
        if (!loadCz(&C2z, p->next)) continue;
        if (strcmp(C1z.clone, C2z.clone)==0) continue;

        Zsulston(&C1z,&C2z,&Sz);
        if (ZboolCpM()) {
           if (Sz.mark > 0) sprintf(mk, "%2d",Sz.mark);
           else strcpy(mk,"  ");;
           sprintf(ZBuf, "%2d. %4d %12s %2db  %12s %2db  %3d %.0e %s %12s    %s\n", 
             Gzn+1, my_clone.ctg,
             C1z.clone, C1z.nbands, C2z.clone, C2z.nbands, Sz.match, Sz.prob, 
             mk, C2z.parent, C2z.fpnum); Output; 
           cnt++;
        }
     }
     total+= cnt;
     if (cnt > 0) Gz.loner[Gzn++]= lp->index;
     if (Gzn == LGZ) {
        sprintf(str, "Compare KeySet: exceeded internal list limit");
        displaymess(str);
        break;
     }
  }
  if (!Zbatch_flag) {
     sprintf(scoreText,"KeySet %d Hits %d", Gzn, total); Show;
     if (nctg>0) 
        printf("Clones (%d) in keyset and current contig - ignored\n",nctg);
  }
DONE: ;
  if (Zlogfp) fflush(Zlogfp);

  if (Gzn == 0) Gzn = -1;
}
/****************************************************************
                      DEF: OneAgain
****************************************************************/
void Z_OneAgain()
{
  if (Gzn == -1) {
      sprintf(scoreText,"Run Compare Keyset"); Show;
      if (graphActivate(g9c))
        graphBoxDraw(compareBox, BLACK, WHITE);
      return;
  }
  if (Gz.w==0) Gz.w = Gzn-1; else Gz.w--;
  if (Gz.w==0) Gz.w = Gzn-1; else Gz.w--;
  Z_OneNext();
}
/****************************************************************
                      DEF: Z_OneNext
****************************************************************/
void Z_OneNext()
{
CLONE *clp;
struct contig *p, *q;
int best=0, cnt=0;
int left=INT_MAX, right=INT_MIN;
struct marker *markerptr;
struct markertop *mkptr;
char str[200];

  IsMerge;
  
  if (Gzn == -1 || currentctg!=Sz.ctg) {
      sprintf(scoreText,"Run Compare Keyset first."); Show;
      if (graphActivate(g9c))
        graphBoxDraw(compareBox, BLACK, WHITE);
      Zprtype=0;
      return;
  }
  ZclearHigh();

  if (!loadCz(&C1z,Gz.loner[Gz.w])) return;
  clp = arrp(acedata, C1z.cin, CLONE);
  if (clp->ctg == currentctg) {
      ZhighCin(CLAM_CLONE, C1z.cin);
  }
  p = root; q = NULL;
  Gz.np=0;
  Gz.index = -1;
  Gz.box=0;
  for (p=root; p; p = p->new)
  {
     if (!loadCz(&C2z, p->next)) continue;
     if (strcmp(C1z.clone, C2z.clone)==0) continue;
     Zsulston(&C1z,&C2z,&Sz);
     if (!ZboolCpM()) continue;

     if (best < Sz.match) {
            clp = arrp(acedata, p->next, CLONE);
            if (clp->parent != -1)   /* on Add&bury, bury in parent */
                Gz.index = clp->parent;
            else 
                Gz.index = p->next;
            Gz.box = p->box;
            best = Sz.match;
            Gz.left = arrp(acedata, p->next, CLONE)->x;
      }
      left = MiN(left, arrp(acedata, p->next, CLONE)->x);
      right = MaX(right, arrp(acedata, p->next, CLONE)->y);
      Gz.clp[Gz.np++] = arrp(acedata, p->next, CLONE);
      ZhighP(CLAM, p);
      cnt++;
      if (Gz.np == LGZ) {
        sprintf(str, "Compare Singles: exceeded internal list limit of %d",LGZ);
        displaymess(str);
        break;
      }
  }
  if (ctg_window != NULL) {
       clp = arrp(acedata, C1z.cin, CLONE);
       for (mkptr = clp->marker; mkptr != NULL; mkptr = mkptr->nextmarker)
       {
            markerptr = arrp(markerdata,mkptr->markerindex,MARKER);
            if (mkptr->markerindex!=highmark) markerptr->colour = CLAM;
       }
  }
  if (left == INT_MAX) {
      sprintf(scoreText,"%d. Ctg%d %s no longer matches.", 
                             Gz.w+1, C1z.ctg, C1z.clone);
      Gz.x=left;
      return;
  }
  Gz.x = left + (right - left)/2;
  if (Gz.box==0) {
      centre_pos = Gz.x;
      if(ctg_window!=NULL) refresh_all_track_colors();
  }
  if (strcmp(" canon", C1z.parent)==0)
    sprintf(scoreText,"%d. Ctg%d: %s %db  Match %d IsParent",
           Gz.w+1, C1z.ctg, C1z.clone, C1z.nbands, cnt); 
  else 
    sprintf(scoreText,"%d. Ctg%d %s %db  Match %d", Gz.w+1, C1z.ctg, C1z.clone,
                            C1z.nbands, cnt);
  Show;
  Gz.w++;
  if (Gz.w >= Gzn) Gz.w=0;
  redrawfingerprints(); 
  /*ctgdisplay(currentctg);  fred 4/3/02*/
  if(ctg_window!=NULL) refresh_all_track_colors();
}
/****************************************************************
                      DEF: positionGz
ADD clone to contig
****************************************************************/
static void positionGz(int how)
{
CLONE *clp;
struct contig *p;
int draw=0, n,  a;
char str[200];

  IsMerge;
  if (Gzn == -1 || currentctg!=Sz.ctg) {
      sprintf(scoreText,"Compare & Next."); Show;
      if (graphActivate(g9c))
        graphBoxDraw(compareBox, BLACK, WHITE);
      Zprtype=0;
      return;
  }

  if (Gz.w==0) a = Gzn-1; else a = Gz.w-1;
  clp = arrp(acedata, Gz.loner[a], CLONE);
  if (clp->ctg!=0) {
      sprintf(scoreText, "Not moved! %s in ctg%d",clp->clone, clp->ctg); Show;
      displaymess(scoreText);
      return;
  }
  if (Gz.x == INT_MAX) {
      sprintf(scoreText, "Not moved! %s no position",clp->clone); Show;
      return;
  }

  if (how==0) {
     clp->x = Gz.x - (clp->fp->b2/2);
     clp->y = Gz.x + (clp->fp->b2/2);
     if (clp->fp->b2 % 2 == 1) clp->y++;;
  }
  else { /* buried */
     clp->x = Gz.left;
     clp->y = Gz.left + clp->fp->b2;
  }
  Zsave_selected(0);
  clp->selected = 1;
  move_selected(0, currentctg, 0);
  clp->selected = 0;
  Zredo_selected(0);

  sprintf(str,"Add clone %s to ctg%d",clp->clone, currentctg);

  for (n=0; n< Gz.np; n++)
       ZhighClp(CLAM, Gz.clp[n]);

  for (p=root; p!=NULL && arrp(acedata, p->next, CLONE)!= clp; p = p->new);
  if (p==NULL) return;

  if (how == 0) {
      sprintf(scoreText, "Add clone %s in ctg%d",clp->clone, currentctg); Show;
      draw = cloneHigh(p, 0);
  }
  else {
      if (Gz.index != -1) {
        sprintf(scoreText, "Bury clone %s in %s",clp->clone, 
               arrp(acedata, Gz.index, CLONE)->clone); Show;
        bury(p->next, Gz.index);
        draw = cloneHigh(p, 0);
      }
      else {
        sprintf(scoreText, "No parent for %s",clp->clone); Show;
      }
  }
  if (!draw)
    ctgdisplay(currentctg); 
}

/****************************************************************
                      DEF: OneAdd
After Compare Keyset, either Add or Add&bury
****************************************************************/
void Z_OneAdd()
{
positionGz(0);
}
void Z_OneBury()
{
positionGz(1);
}

/******************************************************************
                        Find Canonical
*****************************************************************/
int sortBz(struct tmpBz *a, struct tmpBz *b)
{
   if (a->nbands < b->nbands) return 1;
   if (a->nbands > b->nbands) return -1;
   return 0;
}
/****************************************************************
                      DEF: BurCtg
Find potential buried clones
****************************************************************/
void Z_BurCtg()
{
int i, j, k;
int cin, cnt=0,  bad=0;
struct tmpBz *tmz;
CLONE *clp;
char buf[120];
int sortBz();
float f;

  IsMerge;
  if (!Zall_ok(1, 3)) return;

  if (Gzn != -1) {
    Gzn = -1;
    Zprtype=0;
  }
  sprintf(ZBuf,"\n>> Find Canonicals in Ctg%d  (Tol %d Bury~ %3.2f)\n", 
               currentctg, Pz.tol, Pz.burFlt); Output;

  Bznp=Bznb=Bzz=Bzn = Bzp = 0;
  ZFREE(Bz,"Bz");

  cnt=contigs[currentctg].count;
  tmz = (struct tmpBz *) malloc(cnt * sizeof(struct tmpBz));
  NOMEM2(tmz, "tmz");

  for (i=0; i< cnt; i++)
  {
     clp = arrp(acedata, root[i].next, CLONE);
     tmz[i].diff = 0;
     tmz[i].cin = root[i].next;     
     tmz[i].mattype = clp->mattype; /* 0, PARENT, or other */
     tmz[i].parent = clp->parent;   /* -1 or parent index */
     if (clp->fp!=NULL)       
        tmz[i].nbands = clp->fp->b2;
  }
  qsort(tmz, cnt, sizeof(struct tmpBz), (void *)sortBz);

  for (f=0.0; f <= Pz.burFlt; f+= 0.025) 
  {
     for (i=0; i< cnt; i++)
     { 
         if (graphInterruptCalled()) { /* FIX 17mar99 */
              printf("User Interrupt - pre-mature termination of Find Canonical\n");
              break;
         } 
         if (tmz[i].parent > -1) continue; /*if buried, cant be parent*/
         if (!loadCz(&C1z, tmz[i].cin)) continue;

         for (j=i+1; j<cnt; j++) {
             if (tmz[j].parent > -1) continue; /*if buried, cant be buried */
             if (IsSeq(arrp(acedata, tmz[j].cin, CLONE))) continue; /* 19 June 96 */
             if (!loadCz(&C2z, tmz[j].cin)) continue;
             Zgetmatch(&C1z,&C2z,&Sz);
             if (IsBuried2(tmz[j].nbands, f))
             {
                 tmz[j].diff = tmz[j].nbands-Sz.match;
                 if (tmz[j].mattype == PARENT || tmz[j].mattype == PSPARENT) {
                   for (bad=k=0; k<cnt && !bad; k++) {
                     if (tmz[k].parent == tmz[j].cin) {
                        if (!loadCz(&C2z, tmz[k].cin)) return;
                        Zgetmatch(&C1z,&C2z,&Sz);
                        if (!IsBuried2(tmz[k].nbands, f)) bad=1; 
                        else tmz[k].diff = tmz[k].nbands-Sz.match;
                     }
                   }
                   if (bad) continue;
                   for (k=0; k<cnt; k++) 
                     if (tmz[k].parent == tmz[j].cin) 
                         tmz[k].parent = tmz[i].cin;
                 }
                 if (tmz[j].parent != tmz[i].cin) tmz[i].parent = -2;
                 tmz[j].parent = tmz[i].cin;
                 tmz[j].mattype = 0;
                 tmz[i].mattype = PARENT;
            }
         }
     }
  }
      /** all children get put in structure, though may be ignored 
          if parent is not put in; parent is only put in if new buried */
  for (i=0; i< cnt; i++) {
      if (tmz[i].parent == -2) Bznp++;
      else if (tmz[i].parent > -1) Bznb++;
  }
  Bzn = Bznp+Bznb;

  if (Bznp== 0) {
      Bzn = -1;
      if (graphActivate(g9c))
        graphBoxDraw(findburyBox, BLACK, WHITE);
      Bznb = 0;
  }
  else {
     Bznb=0;
     Bz = (struct tmpBz *) malloc(Bzn * sizeof(struct tmpBz));
     NOMEM2(Bz, "Bz");
     for (j=i=0; i< cnt; i++) 
         if (tmz[i].parent== -2) Bz[j++] = tmz[i];
     for (i=0; i< cnt; i++) 
         if (tmz[i].parent > -1) Bz[j++] = tmz[i];

     if (Pz.logFlag || Pz.stdFlag) {
        for (i=0; i < Bznp; i++) {
           clp = arrp(acedata, Bz[i].cin, CLONE);
           cin = Bz[i].cin;
           sprintf(ZBuf, "%-12s: ", clp->clone); 
           for (j=Bznp; j<Bzn; j++) 
             if (Bz[j].parent==cin) {
               sprintf(buf,"%s-%db-%d ",
                   arrp(acedata,Bz[j].cin, CLONE)->clone, 
                   arrp(acedata,Bz[j].cin, CLONE)->fp->b2, Bz[j].diff);
               if (strlen(buf)+strlen(ZBuf)< sizeof(ZBuf)) strcat(ZBuf, buf); 
               Bznb++;
             }
           strcat(ZBuf, "\n"); 
           Output; 
        }
     }
     if (graphActivate(g9c))
        graphBoxDraw(findburyBox, BLACK, LIGHTGRAY);
  } 
  sprintf(scoreText,"Canonical %d  Hits %d",Bznp, Bznb); Show;

  ZFREE(tmz,"tmz");
  if (Zlogfp) fflush(Zlogfp);
}
/****************************************************************
                      DEF: BurAgain
****************************************************************/
void Z_BurAgain()
{
  if (Bzn == -1 || currentctg!=Sz.ctg) {
      sprintf(scoreText,"Find Canonical first"); Show;
      if (graphActivate(g9c))  graphBoxDraw(findburyBox, BLACK, WHITE); 
      return;
  }
  if (Bzz==0) Bzz = Bznp-1; else Bzz--;
  if (Bzz==0) Bzz = Bznp-1; else Bzz--;
  Z_BurNext();
}
/****************************************************************
                      DEF: Z_BurNext
****************************************************************/
void Z_BurNext()
{
int cin, j, cnt;

  IsMerge;
  if (Bzn == -1 || currentctg!=Sz.ctg) {
      sprintf(scoreText,"Find Canonical first"); Show;
      if (graphActivate(g9c))  graphBoxDraw(findburyBox, BLACK, WHITE); 
      return;
  }
  ZclearHigh();
  if (Bzz+1 == Bznp) Bzz=0; else Bzz++;
  cin = Bz[Bzz].cin;
  for (cnt=0, j=Bznp; j< Bzn; j++) 
       if (Bz[j].parent == cin) {
          ZhighCin(CLAM, Bz[j].cin);
          cnt++;
       }
           /* have to find each time cause there was a change to root */
  ZhighCin(CLAM_CLONE, cin);

  /*fred 5/7/03 -- center display on colored clone*/
  centre_pos = arrp(acedata,cin,CLONE)->x;

  sprintf(scoreText,"%d. Clone: %s contains %d", Bzz+1, 
         arr(acedata,cin,CLONE).clone, cnt); Show;
  redrawfingerprints();
  /*ctgdisplay(currentctg);  fred 4/3/02*/
  if(ctg_window!=NULL) refresh_all_track_colors();
}
/****************************************************************
                      DEF: BurAdd
****************************************************************/
void Z_BurAdd()
{
CLONE *clp, *p;
int cnt,j, cin;
struct contig *q;

  IsMerge;
  if (Bzn == -1 || currentctg!=Sz.ctg) {
      sprintf(scoreText,"Find Canonical & Next"); Show;
      return;
  }
  ZclearHigh();
  cin = Bz[Bzz].cin;
  p = arrp(acedata, Bz[Bzz].cin, CLONE);

  for (cnt=j=0; j< Bzn; j++) {
       if (Bz[j].parent == cin) {
           clp = arrp(acedata, Bz[j].cin, CLONE);
           if (clp->ctg != currentctg) {
               printf("Clone %s is no longer in contig\n", clp->clone);
               continue;
           }
           if (clp->parent == cin) continue;
           clp->mattype = 0; /* these may have had previous relation */
           clp->parent = -1;
           strcpy(clp->match, "     ");
           cnt++;
           bury(Bz[j].cin, Bz[Bzz].cin);
           if (Bz[j].diff==0) clp->mattype = EXACT;
           else clp->mattype = APPROX;
           Zsave_selected(0);
           child_adjustment(p, clp);
           Zredo_selected(1);
       }
  }
  for (q=root; q!=NULL &&  q->next!= cin; q = q->new);
  if (q!=NULL) 
   {
        q->box=0; /* force a redisplay */
        cloneHigh(q, 0);
   }
  sprintf(scoreText,"Canonical: %s  buried %d", 
            arr(acedata,cin,CLONE).clone, cnt); Show;
  redrawfingerprints();
  ctgdisplay(currentctg);  /*fred 4/3/02*/
}
/****************************************************************
                       Def: Zsel_unbury()
****************************************************************/
void Zsel_unbury()
{
int i, j;
CLONE *clp;

     IsMerge;
PRTMESS=0;
     for (j=0, i= contigs[currentctg].start; i != -1; i = clp->next)
     {
        clp = arrp(acedata, i, CLONE);
        if (clp->selected==1) 
          if (clp->match[0] != ' ') {
             unbury(i);
             j++;
          }
     }
PRTMESS=1;
  ctgdisplay(currentctg);
  sprintf(ZBuf,"Unbury %d", j); showClam(); 
}
/****************************************************************
                       Def: Zall_unbury()
****************************************************************/
void Zall_unbury()
{
struct contig *p;

     if(!qstuff){  /*efriedr -- added condition for Q reanalyze 12/6/01*/
        if (!messQuery("Say Yes to unbury everything")) return;
     }
     IsMerge;
     Zsave_selected(0);
     for (p = root; p != NULL; p = p->new)
           arrp(acedata,p->next,CLONE)->selected = 1;
     Zsel_unbury();
     Zredo_selected(1);
     ctgdisplay(currentctg);
}
/****************************************************************
                       Def: Zsel_allbury()
Bury non-selected in selected - function in the Rule Menu
****************************************************************/
void Zsel_allbury()
{
int k, i,j;
CLONE *clp2, *clp1;
float best=0.0;
int save, flag;

     IsMerge;
     PRTMESS=0;
     Zsave_selected(0);
     for (i=j=0; i < contigs[currentctg].count; i++) /* potential children */
     {
        if (SS[i].sel==1) continue;
        flag=0;
        clp1 = arrp(acedata, SS[i].cin, CLONE);
        if (IsSeq(clp1)) {
           sprintf(ZBuf,"Warning - Clone %s selected for sequencing, so not buried",
                  clp1->clone);
           displaymess(ZBuf);
           if (clp1->x==INT_MIN) flag=1; /* ok.c, no coords for this clone */
           else continue;
        }
        if (clp1->mattype==PARENT || clp1->mattype==PSPARENT) {
           sprintf(ZBuf,"Warning - Clone %s is parent, so not buried",clp1->clone);
           displaymess(ZBuf);
           if (clp1->x==INT_MIN) flag=1; /* ok.c, no coords for this clone */
           else continue;
        }
        if (clp1->match[0] != ' ') continue;
        if (!loadCzfast(&C1z, SS[i].cin)) continue;
        j++;
        best = 100.0;
        save = -1;

        for (k=0; k < contigs[currentctg].count; k++) /* potential parent */
        {
             clp2 = arrp(acedata, SS[k].cin, CLONE);
             if (SS[k].sel==0 && clp2->match[0]==' ') continue;

             if (!loadCzfast(&C2z, SS[k].cin)) continue;
             Zsulston(&C1z,&C2z,&Sz);
             if (Sz.prob <= best) {
                 if (clp2->match[0] == ' ') save= SS[k].cin;
                 else save = clp2->parent;
                 best = Sz.prob;
             }
         }
         if (save != -1) {
             if (!flag) bury(SS[i].cin, save); /* child, parent */
             clp2 = arrp(acedata, save, CLONE);
             child_adjustment(clp2, clp1); /* parent, child */
         }
     }
  Zredo_selected(1);
  PRTMESS=1;
  ctgdisplay(currentctg);
  sprintf(ZBuf,"Bury %d", j); showClam(); 
}
/****************************************************************
                       Def: Zsel_bury()
bury selected in best clone - on Rule Menu and called by ok.c
****************************************************************/
int Zsel_bury()
{
int i,k, j;
CLONE *clp2, *clp1;
double best=0.0;
int cnt=0, save, pm;

     IsMerge2;
     Zsave_selected(0);
     pm = PRTMESS;
     PRTMESS=0;
     for (i=j=0; i < contigs[currentctg].count; i++) /* potential children */
     {
        if (SS[i].sel==0) continue;
        clp1 = arrp(acedata, SS[i].cin, CLONE);
        /* CAS 13apr03 quit putting on end - for CBlayout, need to be buried
           inorder to move with CBmap to new contig 
        if (IsSeq(clp1)) {
           sprintf(ZBuf,"Warning - Clone %s selected for sequencing, so not buried",
                       clp1->clone);
           displaymess(ZBuf);
           continue;
        }*/
        if (clp1->mattype==PARENT || clp1->mattype==PSPARENT) {
           sprintf(ZBuf,"Warning - Clone %s is parent, so not buried",clp1->clone);
           displaymess(ZBuf);
           continue;
        }
        if (clp1->match[0] != ' ') {
           clp2 = arrp(acedata, clp1->parent, CLONE);
           child_adjustment(clp2, clp1); /* parent, child */
           continue;
        }
        if (!loadCzfast(&C1z, SS[i].cin)) continue;

        j++;
        best = 100.0;
        save = -1;

        for (k=0; k < contigs[currentctg].count; k++) /* potential parent */
        {
             clp2 = arrp(acedata, SS[k].cin, CLONE);
             if (SS[k].sel==1 && clp2->match[0]==' ') continue;

             if (!loadCzfast(&C2z, SS[k].cin)) continue;
             Zsulston(&C1z,&C2z,&Sz);
             if (Sz.prob <= best) {
                 if (clp2->match[0] == ' ') save= SS[k].cin;
                 else save = clp2->parent;
                 best = Sz.prob;
             }
         }
         if (save != -1) {
             cnt++;
             bury(SS[i].cin, save); /* child, parent */
             clp2 = arrp(acedata, save, CLONE);
             child_adjustment(clp2, clp1); /* parent, child */
         }
    }
    Zredo_selected(1);
    PRTMESS=pm;
    if (PRTMESS) sprintf(ZBuf,"Bury %d", j); showClam(); 
    ctgdisplay(currentctg);
return cnt;
}
